﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;

namespace PocketPasswordGen
{
    public static class Password
    {
        static string lowerCase   = @"abcdefghijklmnopqrstuvwyxz";
        static string upperCase   = @"ABCDEFGHIJKLMNOPQRSTUVWYXZ";
        static string numbers     = @"0123456789";
        static string punctuation = @"~!@#$%^&*()-+='"",.?";

        static Dictionary<string, string> phoneticAlphabet = new Dictionary<string,string>();

        public static int PasswordLength { get; set; }

        public static bool ShowPhonetics { get; set; }

        public static bool IncludeLowerCase { get; set; }

        public static bool IncludeUpperCase { get; set; }

        public static bool IncludeNubmers { get; set; }

        public static bool IncludePuncation { get; set; }

        static Password()
        {
            phoneticAlphabet.Add("a", "Alpha");
            phoneticAlphabet.Add("b", "Bravo");
            phoneticAlphabet.Add("c", "Charlie");
            phoneticAlphabet.Add("d", "Delta");
            phoneticAlphabet.Add("e", "Echo");
            phoneticAlphabet.Add("f", "Foxtrot");
            phoneticAlphabet.Add("g", "Golf");
            phoneticAlphabet.Add("h", "Hotel");
            phoneticAlphabet.Add("i", "India");
            phoneticAlphabet.Add("j", "Juliet");
            phoneticAlphabet.Add("k", "Kilo");
            phoneticAlphabet.Add("l", "Lima");
            phoneticAlphabet.Add("m", "Mike");
            phoneticAlphabet.Add("n", "November");
            phoneticAlphabet.Add("o", "Oscar");
            phoneticAlphabet.Add("p", "Papa");
            phoneticAlphabet.Add("q", "Quebec");
            phoneticAlphabet.Add("r", "Romeo");
            phoneticAlphabet.Add("s", "Sierra");
            phoneticAlphabet.Add("t", "Tango");
            phoneticAlphabet.Add("u", "Uniform");
            phoneticAlphabet.Add("v", "Victor");
            phoneticAlphabet.Add("w", "Whiskey");
            phoneticAlphabet.Add("x", "X-ray");
            phoneticAlphabet.Add("y", "Yankee");
            phoneticAlphabet.Add("z", "Zulu");

            phoneticAlphabet.Add("A", "ALPHA");
            phoneticAlphabet.Add("B", "BRAVO");
            phoneticAlphabet.Add("C", "CHARLIE");
            phoneticAlphabet.Add("D", "DELTA");
            phoneticAlphabet.Add("E", "ECHO");
            phoneticAlphabet.Add("F", "FOXTROT");
            phoneticAlphabet.Add("G", "GOLF");
            phoneticAlphabet.Add("H", "HOTEL");
            phoneticAlphabet.Add("I", "INDIA");
            phoneticAlphabet.Add("J", "JULIET");
            phoneticAlphabet.Add("K", "KILO");
            phoneticAlphabet.Add("L", "LIMA");
            phoneticAlphabet.Add("M", "MIKE");
            phoneticAlphabet.Add("N", "NOVEMBER");
            phoneticAlphabet.Add("O", "OSCAR");
            phoneticAlphabet.Add("P", "PAPA");
            phoneticAlphabet.Add("Q", "QUEBEC");
            phoneticAlphabet.Add("R", "ROMEO");
            phoneticAlphabet.Add("S", "SIERRA");
            phoneticAlphabet.Add("T", "TANGO");
            phoneticAlphabet.Add("U", "UNIFORM");
            phoneticAlphabet.Add("V", "VICTOR");
            phoneticAlphabet.Add("W", "WHISKEY");
            phoneticAlphabet.Add("X", "X-RAY");
            phoneticAlphabet.Add("Y", "YANKEE");
            phoneticAlphabet.Add("Z", "ZULU");

            phoneticAlphabet.Add("0", "Zero");
            phoneticAlphabet.Add("1", "One");
            phoneticAlphabet.Add("2", "Two");
            phoneticAlphabet.Add("3", "Three");
            phoneticAlphabet.Add("4", "Four");
            phoneticAlphabet.Add("5", "Five");
            phoneticAlphabet.Add("6", "Six");
            phoneticAlphabet.Add("7", "Seven");
            phoneticAlphabet.Add("8", "Eight");
            phoneticAlphabet.Add("9", "Nine");

            phoneticAlphabet.Add("~", "Tilda");
            phoneticAlphabet.Add("!", "Exclamation Mark");
            phoneticAlphabet.Add("@", "At Symbol");
            phoneticAlphabet.Add("#", "Pound Sign");
            phoneticAlphabet.Add("$", "Dollar Sign");
            phoneticAlphabet.Add("%", "Percent");
            phoneticAlphabet.Add("^", "Carrot Symbol");
            phoneticAlphabet.Add("&", "Ampersand");
            phoneticAlphabet.Add("*", "Asterisk");
            phoneticAlphabet.Add("(", "Left Parenthesis");
            phoneticAlphabet.Add(")", "Right Parenthesis");
            phoneticAlphabet.Add("-", "Minus Sign");
            phoneticAlphabet.Add("+", "Plus Sign");
            phoneticAlphabet.Add("=", "Equals Sign");
            phoneticAlphabet.Add("'", "Apostrophe");
            phoneticAlphabet.Add("\"", "Quote");
            phoneticAlphabet.Add(",", "Comma");
            phoneticAlphabet.Add(".", "Period");
            phoneticAlphabet.Add("?", "Question Mark");
        }

        public static string Generate()
        {
            if ((IncludeLowerCase || IncludeUpperCase || IncludeNubmers || IncludePuncation) == false)
                throw new ArgumentException("You must include at least one character group.");

            string passwordCharaters = string.Empty;
            string password = string.Empty;

            if (IncludeLowerCase == true)
                passwordCharaters += lowerCase;

            if (IncludeUpperCase == true)
                passwordCharaters += upperCase;

            if (IncludeNubmers == true)
                passwordCharaters += numbers;

            if (IncludePuncation == true)
                passwordCharaters += punctuation;

            for (int i = 0; i < PasswordLength; i++)
            {
                // Use a 4-byte array to fill it with random bytes and convert it then
                // to an integer value.
                byte[] randomBytes = new byte[4];

                // Generate 4 random bytes.
                RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
                rng.GetBytes(randomBytes);

                // Convert 4 bytes into a 32-bit integer value.
                int seed = (randomBytes[0] & 0x7f) << 24 |
                            randomBytes[1] << 16 |
                            randomBytes[2] << 8 |
                            randomBytes[3];


                password += passwordCharaters[new Random(seed).Next(0, passwordCharaters.Length)];
            }

            return password;
        }

        public static string ConvertToPhonetic(string password)
        {
            string phoneticPassword = string.Empty;

            if (ShowPhonetics == false)
                return phoneticPassword;

            for (int i = 0; i < password.Length; i++)
            {
                string letter = password[i].ToString();
                phoneticPassword += phoneticAlphabet[letter];

                if (i < password.Length - 1)
                    phoneticPassword += ", ";
            }

            return phoneticPassword;
        }
    }
}
